﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using YJKGeometryFuncs;
using YJKPatternSign.StairsRoomPlanSign.ModelLayer;

namespace YJKPatternSign.StairsRoomPlanSign
{
	public static class StairsDimensionUtilityMethod
	{
		public static bool TryFindANearBoundaryByStairsRun(StairsRunPacker inputPacker, int useIndex, List<Curve> lstAllBoundary, out Curve findeCurve)
		{
			findeCurve = null;
			Curve curve = null;
			double val = double.MaxValue;
			XYZ xyz = inputPacker.GetStairRunMidLine(true).Direction;
			if (useIndex == 0)
			{
				xyz = -xyz;
			}
			Curve stairRunEndCurve = inputPacker.GetStairRunEndCurve(useIndex, false);
			foreach (XYZ xyz2 in new List<XYZ>
			{
				stairRunEndCurve.GetEndPoint(1),
				stairRunEndCurve.GetEndPoint(0),
				inputPacker.GetStairRunMidLine(false).GetEndPoint(useIndex)
			})
			{
				if (StairsDimensionUtilityMethod.TryFindABoundaryByPointAndDriection(xyz2, xyz, lstAllBoundary, out curve) && Geometry.LessThan(curve.Distance(xyz2), val))
				{
					findeCurve = curve;
					val = curve.Distance(xyz2);
				}
			}
			if (null == findeCurve)
			{
				return false;
			}
			Curve curve2 = findeCurve.Clone();
			curve2.MakeUnbound();
			findeCurve = null;
			double parameter = curve2.Project(stairRunEndCurve.GetEndPoint(0)).Parameter;
			double parameter2 = curve2.Project(stairRunEndCurve.GetEndPoint(1)).Parameter;
			if (Geometry.IsEqual(parameter, parameter2))
			{
				return false;
			}
			curve2.MakeBound(Math.Min(parameter2, parameter), Math.Max(parameter2, parameter));
			findeCurve = curve2;
			return true;
		}

		public static bool TryFindALstBoundaryByStairsRun(StairsRunPacker inputPacker, int useIndex, List<Curve> lstAllBoundary, out List<KeyValuePair<double, Curve>> lstFinderValues)
		{
			lstFinderValues = new List<KeyValuePair<double, Curve>>();
			Curve curve = null;
			XYZ xyz = inputPacker.GetStairRunMidLine(true).Direction;
			if (useIndex == 0)
			{
				xyz = -xyz;
			}
			Curve stairRunEndCurve = inputPacker.GetStairRunEndCurve(useIndex, false);
			foreach (XYZ xyz2 in new List<XYZ>
			{
				stairRunEndCurve.GetEndPoint(1),
				stairRunEndCurve.GetEndPoint(0),
				inputPacker.GetStairRunMidLine(false).GetEndPoint(useIndex)
			})
			{
				curve = null;
				if (StairsDimensionUtilityMethod.TryFindABoundaryByPointAndDriection(xyz2, xyz, lstAllBoundary, out curve))
				{
					lstFinderValues.Add(new KeyValuePair<double, Curve>(curve.Distance(xyz2), curve));
				}
			}
			for (int i = 0; i < lstFinderValues.Count; i++)
			{
				Curve curve2 = lstFinderValues[i].Value.Clone();
				curve2.MakeUnbound();
				double parameter = curve2.Project(stairRunEndCurve.GetEndPoint(0)).Parameter;
				double parameter2 = curve2.Project(stairRunEndCurve.GetEndPoint(1)).Parameter;
				if (Geometry.IsEqual(parameter, parameter2))
				{
					lstFinderValues.RemoveAt(i);
					i--;
				}
				else
				{
					curve2.MakeBound(Math.Min(parameter2, parameter), Math.Max(parameter2, parameter));
					lstFinderValues[i] = new KeyValuePair<double, Curve>(lstFinderValues[i].Key, curve2);
				}
			}
			if (lstFinderValues.Count == 0)
			{
				return false;
			}
			lstFinderValues = (from k in lstFinderValues
			orderby k.Key
			select k).ToList<KeyValuePair<double, Curve>>();
			return true;
		}

		public static bool TryFindABoundaryByPointAndDriection(XYZ inputPoint, XYZ driection, List<Curve> lstInputCurve, out Curve findedValue)
		{
			new List<Curve>();
			findedValue = null;
			double val = double.MaxValue;
			foreach (Curve curve in lstInputCurve)
			{
				XYZ xyz;
				if (driection.IsAlmostEqualTo(Utility.CalculateDistanceVetcor(inputPoint, curve, out xyz), CmdStairsRoomPlanSign.NearTolerance) && Geometry.LessThan(inputPoint.DistanceTo(xyz), val))
				{
					findedValue = curve;
					val = inputPoint.DistanceTo(xyz);
				}
			}
			return !(null == findedValue);
		}
	}
}
